#region

using System;
using System.ComponentModel;
using System.Reflection;
using CommandLineMapper.Helpers;
using CommandLineMapper.Interfaces;

#endregion

namespace CommandLineMapper {
    public class PropertyHandlerFactory : IPropertyHandlerFactory {
        #region Implementation of IPropertyHandlerFactory

        public IPropertyHandler Create(PropertyInfo propertyInfo) {
            AssertUtils.AssertArgumentNull(propertyInfo, "propertyInfo");
            ICommandOption commandOption = GetCommandOption(propertyInfo);
            if (commandOption == null) {
                return null;
            }

            AssertUtils.AssertArgument(
                !IsTypeMatches(commandOption.OptionType, propertyInfo.PropertyType),
                "OptionType property of CommandLineAttribute must be the same as property type where it's applied"
                );

            if(!IsConversionSupported(commandOption)) {
                    throw new InvalidOperationException(
                        String.Format("Can not convert from string to {0}", commandOption.OptionType.Name));
            }

            return new PropertyHandler(propertyInfo, commandOption);
        }

        #endregion

        private static ICommandOption GetCommandOption(PropertyInfo propertyInfo) {
            object[] customAttributes = propertyInfo.GetCustomAttributes(typeof (ICommandOption), true);
            if (customAttributes.Length == 0) {
                return null;
            }

            ICommandOption commandOption = customAttributes[0] as ICommandOption;
            return commandOption;
        }
        
        private static bool IsTypeMatches(Type optionType, Type propertyType)
        {
            return (optionType == propertyType);
        }

        private static bool IsConversionSupported(ICommandOption commandOption)
        {
            TypeConverter converter = commandOption.Converter;
            return converter.CanConvertFrom(typeof(string));
        }

    }
}